<?php
/**
 * 基础服务类
 * Created by PhpStorm.
 * User: Yui
 * Date: 2017/3/30 0030
 * Time: 10:39
 */

namespace common\services;

use common\library\comFun;
use Yii;
use yii\data\Pagination;

abstract class BaseSve
{

    /**
     * 模型名
     * @var string
     */
    public $modelName;

    /**
     * 为modelName初始化
     */
    public function __construct()
    {
        $this->modelName = substr(get_class($this), 16, -3);
    }

    /**
     *
     * @param $name
     * @param $arguments
     * @return array
     */
    public function __call($name, $arguments)
    {
        return self::result('The ' . $name . ' method does not exist', -49);
    }

    /**
     * 公共单表查询方法
     * @param array $where 条件
     * @param string $orderBy 排序
     * @param bool $isPaging 是否分页
     * @return array
     */
    public function getList($where = [], string $orderBy = '', bool $isPaging = false):array
    {
        //处理模型名
        $modelName = '\common\models\\' . $this->modelName;;
        $Model = $modelName::find();
        if (!empty($where)) {
            $Model->where($where);
        }
        //要返回的数据
        $returnData = [];
        //是否分页
        if ($isPaging) {
            //是
            //查询总数
            $count = $Model->count();
            $pagination = new Pagination(['totalCount' => $count]);
            $request = Yii::$app->request;
            $pageSize = $request->get('page_size', 20);
            if (!comFun::isPositiveInt($pageSize)) {
                //如果分页大小不符合规范，默认20
                $pageSize = 20;
            }
            $pagination->pageSize = $pageSize;

            $page = $request->get('page', 1);

            if (!comFun::isPositiveInt($page)) {
                //如果页数不符合规范，默认1
                $page = 1;
            }

            $pagination->page = --$page;
            $list = $Model->orderBy($orderBy)
                ->offset($pagination->offset)
                ->limit($pagination->limit)->all();
            $returnData['list'] = $list;
            $returnData['pageArr'] = [
                'pageSize' => $pagination->pageSize,//分页大小
                'total' => $pagination->totalCount,//总条数
                'pageTotal' => ceil($pagination->totalCount / $pagination->pageSize),//分页数
                'currentPage' => ++$page//当前页
            ];
        } else {
            //否
            $list = $Model->orderBy($orderBy)->all();
            $count = count($list);
            $returnData['list'] = $list;
            $returnData['pageArr'] = [
                'pageSize' => $count,//分页大小
                'total' => $count,//总条数
                'pageTotal' => 1,//分页数
                'currentPage' => 1//当前页
            ];
        }
        return self::result('', 0, $returnData);
    }

    /**
     * 公共添加
     * @param array $data
     * @param string $scenario //场景
     * @return array
     */
    public function add(array $data, string $scenario = ''):array
    {
        try {
            //处理模型名
            $modelName = '\common\models\\' . $this->modelName;
            $Model = new $modelName();
            if ($scenario) {
                $Model->scenario = $scenario;
            }
            $Model->load([$this->modelName => $data]);
            //验证
            self::checkErr($Model);
            //插入
            $rs = $Model->save();
            if ($rs !== true) {
                throw new \Exception('添加失败', -1);
            }
            return self::result('添加成功', 0);
        } catch (\Exception $e) {
            //if (array_key_exists($e->getCode(), OC_ERR_CODE)) {
                return self::result($e->getMessage(), $e->getCode());
            //} else {
               // return self::result('系统繁忙', -50);
           // }
        }
    }

    /**
     * 公共信息查看方法
     * @param $where
     * @return array
     */
    public function getInfo($where):array
    {
        try {
            //处理模型名
            $modelName = '\common\models\\' . $this->modelName;
            //查找出模型
            $Model = $modelName::find()->where($where)->one();
            if (empty($Model)) {
                throw new \Exception('找不该信息', -1);
            }
            return self::result('', 0, ['Obj' => $Model]);
        } catch (\Exception $e) {
            if (array_key_exists($e->getCode(), OC_ERR_CODE)) {
                return self::result($e->getMessage(), $e->getCode());
            } else {
                return self::result('系统繁忙', -50);
            }
        }
    }

    /**
     * 公共更新
     * @param array $data
     * @param string $scenario //场景
     * @return array
     */
    public function update(array $data, string $scenario = ''):array
    {
        try {
            //处理模型名
            $modelName = '\common\models\\' . $this->modelName;
            //主键名
            $primaryKey = $modelName::primaryKey()[0];
            $Model = $modelName::findOne($data[$primaryKey]);
            if (empty($Model)) {
                throw new \Exception('找不到修改内容', -1);
            }
            if ($scenario) {
                $Model->scenario = $scenario;
            }
            $Model->load([$this->modelName => $data]);
            //验证
            self::checkErr($Model);
            $rs = $Model->update();
            if ($rs === false) {
                throw new \Exception('保存失败', -1);
            }
            return self::result('保存成功', 0);
        } catch (\Exception $e) {
            if (array_key_exists($e->getCode(), OC_ERR_CODE)) {
                return self::result($e->getMessage(), $e->getCode());
            } else {
                return self::result('系统繁忙', -50);
            }
        }
    }

    /**
     * 公共更新，自定义查询条件
     * @param mixed $where 查询条件
     * @param array $data 排除ID后的数据
     * @param string $scenario //场景
     * @return array
     */
    public function updateByWhere($where, array $data, string $scenario = ''):array
    {
        try {
            //处理模型名
            $modelName = '\common\models\\' . $this->modelName;
            $Model = $modelName::find()->where($where)->one();
            if (empty($Model)) {
                throw new \Exception('找不到修改内容', -1);
            }
            if ($scenario) {
                $Model->scenario = $scenario;
            }
            $Model->load([$this->modelName => $data]);
            //验证
            self::checkErr($Model);
            $rs = $Model->update();
            if ($rs === false) {
                throw new \Exception('保存失败', -1);
            }
            return self::result('保存成功', 0);
        } catch (\Exception $e) {
            if (array_key_exists($e->getCode(), OC_ERR_CODE)) {
                return self::result($e->getMessage(), $e->getCode());
            } else {
                return self::result('系统繁忙', -50);
            }
        }
    }

    /**
     * 公共标记删除
     * @param $where
     * @return array
     */
    public function del($where):array
    {
        try {
            //处理模型名
            $modelName = '\common\models\\' . $this->modelName;
            //查找出模型
            $Model = $modelName::findOne($where);

            if (empty($Model)) {
                return self::result('删除成功', 0);
            }

            $Model->is_del = 1;

            $rs = $Model->update();

            if ($rs === false) {
                throw new \Exception('删除失败', -1);
            }
            return self::result('删除成功', 0);
        } catch (\Exception $e) {
            if (array_key_exists($e->getCode(), OC_ERR_CODE)) {
                return self::result($e->getMessage(), $e->getCode());
            } else {
                return self::result('系统繁忙', -50);
            }
        }
    }

    /**
     * 公共移除方法
     * @param $where
     * @return array
     */
    public function remove($where):array
    {
        try {
            //处理模型名
            $modelName = '\common\models\\' . $this->modelName;
            //查找出模型
            $Model = $modelName::findOne($where);
            if (empty($Model)) {
                return self::result('删除成功', 0);
            }

            $rs = $Model->delete();

            if ($rs === false) {
                throw new \Exception('删除失败', -1);
            }
            return self::result('删除成功', 0);
        } catch (\Exception $e) {
            if (array_key_exists($e->getCode(), OC_ERR_CODE)) {
                return self::result($e->getMessage(), $e->getCode());
            } else {
                return self::result('系统繁忙', -50);
            }
        }
    }

    /**
     * 批量删除
     * @param $where
     * @return array
     */
    public function batchRemove($where)
    {
        try {
            //处理模型名
            $modelName = '\common\models\\' . $this->modelName;
            $rs = $modelName::deleteAll($where);
            if ($rs !== false) {
                return self::result('删除成功', 0);
            } else {
                throw new \Exception('删除失败', -1);
            }
        } catch (\Exception $e) {
            if (array_key_exists($e->getCode(), OC_ERR_CODE)) {
                return self::result($e->getMessage(), $e->getCode());
            } else {
                return self::result('系统繁忙', -50);
            }
        }
    }

    /**
     * 消息发回
     * @param string $msg 消息提示
     * @param int $code 错误代码，默认0为正确，-1代表普通错误，-50系统繁忙，-100为未登录
     * @param array $data 数据
     * @return array
     */
    public static function result($msg = '', $code = -1, $data = []):array
    {
        return ['msg' => $msg, 'code' => $code, 'data' => $data];
    }

    /**
     * 获取全局唯一20位自增id
     * @return string
     */
    public static function getSelfIncId():string
    {
        $cache = Yii::$app->cache;

        //最后生成的时间戳
        $lastTimestamp = $cache->get('lastTimestamp');
        $lastTimestamp = empty($lastTimestamp) ? '' : $lastTimestamp;

        //计数器
        $idStep = $cache->get('idStep');
        $idStep = empty($idStep) ? 0 : intval($idStep);

        //获取当前时间戳
        list($microTime, $second) = explode(' ', microtime());
        //截取微秒字符串
        $microTimeStr = substr($microTime, 2, 6);
        $timestamp = $second . $microTimeStr;

        if ($lastTimestamp === $timestamp) {
            ++$idStep;
        } else {
            $idStep = 0;
            $lastTimestamp = $timestamp;
        }

        $cache->set('lastTimestamp', $lastTimestamp);
        $cache->set('idStep', $idStep);

        $idStepStr = str_pad($idStep, 4, '0', STR_PAD_LEFT);
        $timestamp .= $idStepStr;

        return $timestamp;
    }

    /**
     * 检查错误
     * @param $Model
     * @throws \Exception
     */
    public static function checkErr($Model)
    {
        if ($Model->validate() === false) {
            $firstErrors = $Model->getFirstErrors();
            $firstError = array_shift($firstErrors);
            throw new \Exception($firstError, -1);
        }
    }
}